<?php

namespace App\Api\Services;

use App\Api\Models\LogInStorageModel;
use App\Api\Models\LogOutPackageModel;
use App\Api\Models\LogOutStorageModel;
use App\Api\Models\LogPackageContentModel;
use App\Api\Models\LogPackageModel;
use App\Api\Models\MaterielTypeModel;
use App\Api\Models\SellGoodsDetailBatchModel;
use App\Api\Models\SellGoodsDetailModel;
use App\Api\Models\SellMaterielPrepareOutLogModel;
use App\Api\Models\SellModel;
use App\Api\Models\SellPackageContentModel;
use App\Api\Models\SellPackageDetailModel;
use App\Api\Models\StorageBatchModel;
use App\Api\Models\StorageManageModel;
use App\Api\Models\StorageModel;
use App\Models\CheckModel;
use App\Models\SellGoodsDetail;
use App\V3\Api\Services\MessageService;
use App\V3\V3_2_7\Services\CheckStorageManageService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\V3\V3_1\Models\SerialNumberModel;
use App\V3\V3_1\Models\MaterielProductContentModel;
class StorageManageService
{
    static public function checkMatierlInStorageOrNot($id, $mainId)
    {
        $info = StorageManageModel::where([
            'type_id' => $id,
            'main_id' => $mainId,
            'delete_flag' => 0
        ])->where('in_storage_num', '!=', 0)->first();

        if(!empty($info)) {
            return false;
        }
        else {
            return true;
        }
    }
    //删除库存信息
    static public function del($data)
    {
        $storageManageInfo = StorageManageModel::where('id', $data['id'])->first();

        if($storageManageInfo['in_storage_num'] != 0) {
            return ['code' => 1, 'msg' => '当商品库存数为0时才可删除，当前库存数为：'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        StorageManageModel::where('id', $data['id'])
        ->update(['delete_flag' => 1]);

        StorageBatchModel::where('storage_manage_id', $data['id'])
            ->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }
    //直接入库(新建入库)
    static public function directInStorage($data)
    {
        $data['alert_num'] = $data['status'] == 1?$data['alert_num']:0;
        $data['remark'] = empty($data['remark'])?'':$data['remark'];

        $materielTypeInfo = MaterielTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost'
        )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->where([
                'materiel_name' => $data['materiel_name'],
                'type_name' => $data['type_name'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
            ])
            ->first();

        if(empty($materielTypeInfo)) {
            return ['code' => 1, 'msg' => '物料`'.$data['materiel_name'].'-'.$data['type_name'].'`不存在', 'data' => ''];
        }

        //仓库信息
        $storageInfo = StorageModel::where([
            'storage_name' => $data['storage_name'],
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        if(empty($storageInfo)) {
            return ['code' => 1, 'msg' => '仓库`'.$data['storage_name'].'`不存在', 'data' => ''];
        }

        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            'main_id' => $data['main_id'],
        ])->first();

        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        if(empty($checkStorageManage)) {
            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $materielTypeInfo['cost'] == 0?0:$materielTypeInfo['cost'],
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => $data['num'],//采购单内物料商品入库数量
                'virtual_storage_num' => $data['num'],
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => time(),//入库时间
                'alert_num' => $data['alert_num'],
                'created_at' => time(),
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
               $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $data['num']
            );
        }
        else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => $data['num'],
                'alert_num' => $data['alert_num'],
                'remark' => $data['remark'],
                'materiel_mean_cost' => $materielTypeInfo['cost'],
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $checkStorageManage['in_storage_num'] + $data['num']
            );
        }

        $inStorageNum = !empty($checkStorageManage)?$checkStorageManage['in_storage_num']:0;

        //入库操作记录
        $logInStorage = [
            'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => $data['num'],//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + $data['num'],//操作后库存数
            'materiel_mean_cost' => 0,//物料均价
            'in_storage_time' => time(),//入库时间
            'remark' => $data['remark'],//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => time()
        ];

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if(!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if(!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num']),
                        'alert_num' => $data['alert_num'],
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        'delete_flag' => 0
                    ]);

                $meanCost =  $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            $checkBatchInfo = StorageBatchModel::where('batch_no', $batchNo)->first();

            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty($checkBatchInfo));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageManageId,
                'batch_num' => $data['num'],
                'batch_left_num' => $data['num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            LogInstorageModel::insert($logInStorage);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (\Exception $e) {
            DB::rollback();
            Log::debug('新建入库(直接入库：'.var_export($e->getMessage(), true));
        }
    }

    //库存查看列表
    static public function list($parentId, $data)
    {
        $keyword = empty($data['keyword'])?'':$data['keyword'];
        $condition = [];
        if(!empty($data['materiel_class_id'])) {
            $condition['d.materiel_class_id'] = ['EQ' => $data['materiel_class_id']];
        }

        $result = StorageManageModel::list($parentId, $keyword, $condition, $data);

        return $result;
    }

    /**
     * 审批出库
     * @param $userId
     * @param $mainId
     * @param $data
     * @param $sellId
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/6 17:13
     * @return array
     */
    static public function checkOutStorage($userId, $mainId, $data, $sellId = 0, $overflowBreakagePackageInfo)
    {
        if(!empty($data['content'])) {
            SELF::materielOutStorage($userId, $mainId, $data, $sellId = 0);
        }

        if(!empty($overflowBreakagePackageInfo)) {
            SELF::packageOutStorage($userId, $mainId, $data, $overflowBreakagePackageInfo);
        }

        return ['code' => 0, 'msg' => '', 'data' => ''];
    }

    static private function packageOutStorage($userId, $mainId, $data, $package)
    {
        //出库信息
        $outStorageNumInfo = [];
        $logPackageInfo = [];

        foreach($package as $key => $value) {
            $logId = LogPackageModel::insertGetId([
                'package_id' => $value['package_id'],
                'package_name' => $value['package_name'],
                'num' => $value['num'],
                'all_id_type' => 1,
                'all_id' => $data['all_id'],
                'user_id' => $userId,
                'main_id' => $mainId,
                'created_at' => time()
            ]);

            foreach($value['package_content'] as $val) {
                if($val['in_storage_num'] < $val['total_num']) {
                    throw new \Exception('库存剩余数量不足');
                }

                if($val['virtual_storage_num'] < $val['total_num']) {
                    throw new \Exception('库存可预出库剩余数量不足');
                }

                LogPackageContentModel::insert([
                    'log_package_id' => $logId,
                    'package_id' => $value['package_id'],
                    'storage_id' => $val['storage_id'],
                    'storage_name' => $val['storage_name'],
                    'storage_address' => $val['storage_address'],
                    'materiel_class_id' => $val['materiel_class_id'],
                    'materiel_class_name' => $val['materiel_class_name'],
                    'materiel_class_no' => $val['materiel_class_no'],
                    'materiel_type_id' => $val['type_id'],
                    'materiel_name' => $val['materiel_name'],
                    'type_name' => $val['type_name'],
                    'materiel_no' => $val['materiel_no'],
                    'operate_num' => $val['total_num'],
                    'out_storage_manage_id' => $val['storage_manage_id'],
                    'last_storage_num' => $val['in_storage_num'],
                    'next_storage_num' => $val['in_storage_num'] - $val['total_num'],
                    'all_id_type' => 2,
                    'all_id' => $data['all_id'],
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time()
                ]);

                StorageManageModel::where('id', $val['storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$val['total_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$val['total_num'])
                    ]);

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['id'],
                    $val['storage_name'],
                    $val['total_num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['storage_name'],
                    $val['id']
                );
                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['storage_name'],
                    $val['total_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['id'],
                    $val['alert_num'],
                );
            }
        }
        return true;
    }

    static private function materielOutStorage($userId, $mainId, $data, $sellId)
    {
        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据

        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                throw new \Exception('物料`'.$value['name'].'-'.$value['type_name'].'`不存在');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                throw new \Exception('仓库`'.$value['warehouse'].'`不存在');
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            //检查库存中是否存在该物料
            if(empty($storageManageInfo)) {
                throw new \Exception('库存中物料`'.$value['name'].'-'.$value['type_name'].'`不存在');
            }

            if($storageManageInfo['in_storage_num'] < $value['num']) {
                throw new \Exception('当前库存剩余数量不足，无法完成出库');
            }

            $logOutPackageData[$key]['storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutPackageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutPackageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutPackageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutPackageData[$key]['out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutPackageData[$key]['mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价

            $price = empty($value['price'])?0:$value['price'];

            $logOutPackageData[$key]['price'] = $data['all_id_type'] == 1?$storageManageInfo['materiel_mean_cost']:$price;
            $logOutPackageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutPackageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutPackageData[$key]['user_id'] = $userId;
            $logOutPackageData[$key]['main_id'] = $mainId;
            $logOutPackageData[$key]['created_at'] = time();
            $logOutPackageData[$key]['num'] = $value['num'];//操作数量

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['created_at'] = time();

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        //生成入库操作记录
        LogOutstorageModel::insert($logOutstorageData);

        LogOutPackageModel::insert($logOutPackageData);

        //更新库存总数
        foreach($outstorageNumsData as $val) {
            StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

            //验证是否有预出库，有则跳过此步骤
            $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                ->where('materiel_type_id', $val['type_id'])->first();

            if(empty($prepareInfo)) {
                StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
            }

            MessageService::sendAlertSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['alert_num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $storageInfo['id'],
                $val['storage_name'],
                $val['num']
            );

            MessageService::sendShortSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $val['storage_name'],
                $storageInfo['id']
            );

            MessageService::sendOutSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['storage_name'],
                $val['num'],
                $datas=['user_id'=>$userId,'main_id' => $mainId],
                $storageInfo['id'],
                $val['alert_num'],
            );
        }

        return true;
    }

    /**
     * @出库
     * @created 在 2021/11/29 19:08 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data['content] 出库物料商品信息
     * @param $data['content]['name] 物料名称
     * @param $data['content]['price] 单价
     * @param $data['content]['type_name] 物料型号
     * @param $data['content]['warehouse] 仓库名
     * @param $data['content]['warehouse_id] 仓库主键id
     * @param $data['content]['num] 出库操作数量
     * @param $data['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data['all_id] 单据id
     * @param $data['out_storage_time] 出库时间
     * @param $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorage($userId, $mainId, $data, $sellId = 0)
    {
        if(empty($data['content'])) {
            return ['code' => 1, 'msg' => '无可出库商品信息', 'data' => ''];
        }

        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据

        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '物料`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`'.$value['warehouse'].'`不存在', 'data' => ''];
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            //检查库存中是否存在该物料
            if(empty($storageManageInfo)) {
                return ['code' => 1, 'msg' => '库存中物料`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            if($storageManageInfo['in_storage_num'] < $value['num']) {
                return ['code' => 1, 'msg' => '当前库存剩余数量不足，无法完成出库', 'data' => ''];
            }

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $value['price'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['created_at'] = time();

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        DB::beginTransaction();

        try {
            //生成入库操作记录
            LogOutstorageModel::insert($logOutstorageData);

            //更新库存总数
            foreach($outstorageNumsData as $val) {
                StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

                //验证是否有预出库，有则跳过此步骤
                if($sellId != 0) {
                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                        ->where('materiel_type_id', $val['type_id'])->first();
                    if(empty($prepareInfo)) {
                        StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                    }
                }

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['storage_name'],
                    $storageInfo['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['storage_name'],
                    $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['alert_num'],
                );
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => $returnData];
        }
        catch(\Exception $e) {
            DB::rollback();
            Log::debug('出库：'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     *
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data['content] 出库物料商品信息
     * @param $data['content]['storage_manage_id] 商品库存id
     * @param $data['content]['price] 单价
     * @param $data['content]['num] 出库操作数量
     * @param $data['content]['batch_info] 批次信息
     * @param $data['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data['all_id] 单据id
     * @param $data['out_storage_time] 出库时间
     * @param $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorageWithBatch($userId, $mainId, $data, $sellId)
    {
        foreach($data['content'] as $value) {
            foreach($value['batch_info'] as $val) {
                //出库商品基础信息
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'b.storage_name',
                    'b.storage_address',
                    'a.type_id',
                    'c.materiel_name',
                    'c.materiel_no',
                    'c.type_name',
                    'a.materiel_class_id',
                    'd.class_name',
                    'd.class_no',
                    'materiel_mean_cost',
                    'in_storage_num'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('storage as b', 'b.id', '=', 'a.storage_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                    ->where([
                        'a.id' => $val['storage_manage_id'],
                        'a.delete_flag' => 0
                    ])->first();

                MessageService::sendAlertSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['alert_num'],
                     $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_name'],
                    $storageManageInfo['storage_id'],
                );

                MessageService::sendOutSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['storage_name'],
                    $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['alert_num'],
                );

                $outStorageLogInfo[] = [
                    'storage_id' => $storageManageInfo['storage_id'],
                    'storage_name' => $storageManageInfo['storage_name'],
                    'storage_address' => $storageManageInfo['storage_address'],
                    'curr_storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['class_name'],
                    'materiel_class_no' => $storageManageInfo['class_no'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'operate_num' => $val['num'],
                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $val['num'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'remark' => $value['remark'],
                    'out_storage_time' => $value['in_storage_time'],
                    'fact_out_time' => time(),
                    'created_at' => time(),
                    'storage_batch_id' => $val['batch_id'],
                ];

                $logOutPackageInfo[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'storage_id' => $storageManageInfo['storage_id'],
                    'out_time' => $value['in_storage_time'],
                    'num' => $val['num'],
                    'mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'price' => $value['price'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time(),
                ];

                $outStorageInfo[] = [
                    'id' =>  $storageManageInfo['id'],
                    'num' => $val['num'],
                ];

                $batchInfo[] = [
                    'id' => $val['batch_id'],
                    'num' => $val['num'],
                ];
            }
        }

        return [
            'data' => $outStorageLogInfo,
            'data1' => $logOutPackageInfo,
            'data2' => $outStorageInfo,
            'data3' => $batchInfo,
        ];
    }

    /**出库撤销回滚数量
     * @created 在 2022/01/11 10:17 创建
     * @param $allIdType 单据类型;1:报损;2:销售;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;
     * @author: Sun Wu
     */
    static public function cancelOut($allIdType, $allId)
    {
        $logOutInfo = LogOutstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logOutInfo)) {
            $item = [];
            foreach($logOutInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logOutInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('in_storage_num', $v['num']);
                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('virtual_storage_num', $v['num']);
            }

            LogOutstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
            LogOutPackageModel::where([
                'all_id_type' => $allIdType,
                'all_id' => $allId
            ])->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageOut($allIdType, $allId)
    {
        $logPackageInfo = LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)->where('is_cancel', 0)->first();

        if(!empty($logPackageInfo)) {
            $logPackageContentInfo = LogPackageContentModel::where([
                'all_id_type' => 4,
                'all_id' => $allId
            ])->get()->toArray();

            foreach($logPackageContentInfo as $value) {
                StorageManageModel::where('id', $value['out_storage_manage_id'])
                    ->update([
                        'delete_flag' => 0,
                        'in_storage_num' => DB::raw('in_storage_num +'.$value['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num +'.$value['operate_num']),
                    ]);
            }
        }

        LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)
            ->update(['is_cancel' => 1]);

        return 1;
    }

    /**入库撤销回滚数量
     * @created 在 2022/01/11 10:47 创建
     * @param $allIdType 单据类型;1:报溢;2:退货;3:采购;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;2:库存数量不足，无法撤销;
     * @author: Sun Wu
     */
    static public function cancelIn($allIdType, $allId)
    {
        $logInInfo = LogInstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logInInfo)) {
            $item = [];
            foreach($logInInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logInInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                if($checkStorageManageInfo['in_storage_num'] < $v['num']) {
                    return 2;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])
                    ->update([
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$v['num']),
                        'in_storage_num' => DB::raw('in_storage_num - '.$v['num']),
                    ]);
            }

            LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageIn($type, $id)
    {
        $logPackageInfo = LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
            ->first();

        try {
            if(!empty($logPackageInfo)) {
                $logPackageContentInfo = LogPackageContentModel::where([
                    'all_id_type' => 5,
                    'all_id' => $id,
                ])
                    ->get()->toArray();

                foreach($logPackageContentInfo as $value) {
                    $storageManageInfo = StorageManageModel::where([
                        'id' => $value['out_storage_manage_id'],
                        'delete_flag' => 0
                    ])
                        ->first()->toArray();
                    //库存中无此商品
                    if(empty($storageManageInfo)) {
                        return 0;
                    }

                    //库存数不足
                    if($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                        return 3;
                    }

                    StorageManageModel::where('id', $value['out_storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num - '.$value['operate_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num - '.$value['operate_num']),
                        ]);
                }
            }

            LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
                ->update(['is_cancel' => 1]);

            DB::commit();
            return 1;
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('套餐入库撤销异常:'.var_export($e->getMessage(), true));
            return 2;
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @modify 在 2022/05/06 16:32 By Sun Wu
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data['content] 入库物料商品信息
     * @param array $data['content]['name'] 物料名称
     * @param array $data['content]['type_name'] 物料名称
     * @param array $data['content]['warehouse'] 仓库名
     * @param array $data['content]['warehouse_id'] 仓库主键id
     * @param array $data['content]['num] 操作数量
     * @param array $data['in_storage_time] 入库时间
     * @param array $data['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data['all_id] 单据id
     * @param array $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function inStorage($userId, $mainId, $data, $batchTitle)
    {

        $logInstorageData = [];//入库操作记录数据
        $existLogInstorageData = [];
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];

        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`'.$value['warehouse'].'`不存在', 'data' => ''];
            }

            if(empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '商品`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            if(empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'main_id' => $mainId,
                    'in_storage_time' => time()
                ];
            }
            else {
                $instorageNumsData[] = [
                    'id' => $storageManageInfo['id'],//库存主键id
                    'in_storage_num' => $value['num'],//入库数量
                    'cost' => $storageManageInfo['materiel_mean_cost'],
                    'materiel_type_id' => $materielTypeInfo['id'],//物料id
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类主键名称
                    'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                    'materiel_class_no' => $materielTypeInfo['class_no'],//物料二级分类编号
                ];
            }
        }

        DB::beginTransaction();

        try {
            if(!empty($instorageNumsData)) {
                //更新库存总数
                foreach($instorageNumsData as $key => $value) {
                    StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num +'.$value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num +'.$value['in_storage_num']),
                            'delete_flag' => 0
                        ]);
                    MessageService::sendInSms(
                        '',
                        $value['materiel_name'],
                        $value['type_name'],
                        $value['storage_id'],
                        $value['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $value['in_storage_num'],
                        $value['in_storage_num']
                    );

                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );

                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $value['id'],
                        'materiel_type_id' => $value['materiel_type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $value['materiel_name'],//物料名称
                        'type_name' => $value['type_name'],//物料型号
                        'materiel_no' => $value['materiel_no'],//物料编号
                        'materiel_class_id' => $value['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $value['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $value['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $value['id'],//仓库主键id
                        'storage_name' => $value['storage_name'],//仓库名
                        'storage_address' => $value['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $value['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => empty($storageManageInfo)?0:$storageManageInfo['materiel_mean_cost'],//物料均价
                        'next_storage_num' => $value['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'created_at' => time(),
                    ]);
                }

            }

            if(!empty($arr)) {
                foreach($arr as $v) {
                    MessageService::sendInSms(
                        '',
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['storage_id'],
                        $v['storage_name'],
                        $datas=['user_id'=>$userId,'main_id' => $mainId],
                        $v['in_storage_num'],
                        $v['in_storage_num']
                    );

                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $insertId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $v['materiel_class_id'],
                        'materiel_class_name' => $v['materiel_class_name'],
                        'materiel_class_no' => $v['materiel_class_no'],
                        'type_id' => $v['type_id'],
                        'materiel_name' => $v['materiel_name'],
                        'type_name' => $v['type_name'],
                        'materiel_no' => $v['materiel_no'],
                        'storage_id' => $v['storage_id'],
                        'storage_name' => $v['storage_name'],
                        'storage_address' => $v['storage_address'],
                        'in_storage_num' => $v['in_storage_num'],
                        'virtual_storage_num' => $v['in_storage_num'],
                        'main_id' => $mainId,
                        'in_storage_time' => time()
                    ]);

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $insertId,
                        0,
                        $v['in_storage_num'],
                        0,
                        $mainId
                    );

                    //生成入库操作记录
                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $insertId,
                        'materiel_type_id' => $v['type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $v['materiel_name'],//物料名称
                        'type_name' => $v['type_name'],//物料型号
                        'materiel_no' => $v['materiel_no'],//物料编号
                        'materiel_class_id' => $v['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $v['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $v['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $v['storage_id'],//仓库主键id
                        'storage_name' => $v['storage_name'],//仓库名
                        'storage_address' => $v['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $v['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => 0,//物料均价
                        'next_storage_num' => $v['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark'])?'':$data['remark'],
                        'created_at' => time(),
                    ]);
                }
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：'.var_export($e->getMessage(), true));
        }
    }

    //批次列表
    static public function batchList($id)
    {
        return StorageManageModel::select(
            'a.id',
            'a.type_id',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->with('batchList', function ($query) {
                $query->select(
                    'storage_batch.id',
                    'storage_batch.id',
                    'batch_no',
                    'storage_manage_id',
                    'batch_num',
                    'batch_left_num',
                    'batch_cost',
                    'purchase_no'
                )
                    ->leftJoin('materiel as b', 'b.id', '=', 'storage_batch.materiel_id');
            })
            ->where('a.id', $id)
            ->first();
    }

    static public function setAlertNum($data)
    {
        StorageManageModel::where('id', $data['id'])->update(['alert_num' => $data['alert_num']]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static public function allocate($data)
    {
        //需调拨物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.alert_num',
            'a.materiel_class_id',
            'a.materiel_mean_cost',
            'a.in_storage_num',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'a.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'a.storage_id',
            'd.storage_name',
            'd.storage_address',
            'e.id as first_class',
            'virtual_storage_num'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->leftJoin('materiel_class as e', 'e.id', '=', 'b.parent_id')
            ->where([
                'a.id' => $data['id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0
            ])->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法完成调拨', 'data' => ''];
        }

        if($storageManageInfo['storage_id'] == $data['storage_id']) {
            return ['code' => 1, 'msg' => '禁止同库调拨', 'data' => ''];
        }

        //调入仓库信息
        $storageInfo = StorageModel::where([
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
        ])->first();

        if(empty($storageInfo)) {
            return ['code' => 1, 'msg' => '调入仓库不存在，无法完成调拨', 'data' => ''];
        }

        if($storageManageInfo['in_storage_num'] < $data['allocate_num']) {
            return ['code' => 1, 'msg' => '调拨数量超出实际库存数，无法完成调拨,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        //检查调入仓库是否存在相同物料商品
        $checkStorageManageInfo = StorageManageModel::where([
            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
            'type_id' => $storageManageInfo['type_id'],
            'storage_id' => $storageInfo['id'],
            'main_id' => $data['main_id'],
        ])
            ->where('id', '!=', $storageManageInfo['materiel_class_id'])->first();

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if(!empty($checkStorageManageInfo)) {
                $meanCost = $checkStorageManageInfo['materiel_mean_cost'];
                StorageManageModel::where('id', $checkStorageManageInfo['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num +'.$data['allocate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num +'.$data['allocate_num']),
                    'delete_flag' => 0
                ]);
                $newStorageId = $checkStorageManageInfo['id'];
            }
            else {
                $meanCost = $storageManageInfo['materiel_mean_cost'];
                $arr = [
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                    'type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $data['allocate_num'],
                    'virtual_storage_num' => $data['allocate_num'],
                    'alert_num' => 0,
                    'materiel_original' => 1,
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'created_at' => time()
                ];

                //不存在相同物料时，新建物料入库信息
                $newStorageId = StorageManageModel::insertGetId($arr);
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';

            do {
                $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('main_id', $data['main_id'])
                ->where('batch_no', $batchNo)->first()));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageId,
                'batch_num' => $data['allocate_num'],
                'batch_left_num' => $data['allocate_num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            //入库操作记录日志
            LogInstorageModel::insert([
                'type' => 1,//日志类型;0:入库;1:调拨入库;2:直接入库;
                'storage_id' => $storageInfo['id'],
                'storage_name' => $storageInfo['storage_name'],
                'storage_address' => $storageInfo['storage_address'],
                'last_storage_id' => $storageManageInfo['storage_id'],
                'last_storage_name' => $storageManageInfo['storage_name'],
                'last_storage_address' => $storageManageInfo['storage_address'],
                'last_storage_manage_id' => $storageManageInfo['id'],
                'curr_storage_manage_id' => $newStorageId,
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['allocate_num'],
                'last_storage_num' => empty($checkStorageManageInfo)?0:$checkStorageManageInfo['in_storage_num'],
                'next_storage_num' => empty($checkStorageManageInfo)?$data['allocate_num']:$checkStorageManageInfo['in_storage_num'] + $data['allocate_num'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'in_storage_time' => time(),
                'created_at' => time()
            ]);

            //出库操作记录日志
            LogOutstorageModel::insert([
                'type' => 1,//type;0:出库;1:调出;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => $storageInfo['id'],
                'next_storage_name' => $storageInfo['storage_name'],
                'next_storage_address' => $storageInfo['storage_address'],
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'next_storage_manage_id' => $newStorageId,
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['allocate_num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time()
            ]);

            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num -'.$data['allocate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num -'.$data['allocate_num']),
                ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num -'.$data['allocate_num'])
                ]);
            }

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                $storageInfo['storage_name'],
                $data['allocate_num'],
                $data,
                $storageInfo['id'],
                $storageManageInfo['alert_num'],
            );

            MessageService::sendInSms(
                '无',
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['allocate_num'],
                empty($checkStorageManageInfo)?$data['allocate_num']:$data['allocate_num'] + $checkStorageManageInfo['in_storage_num']
            );

            $currStorageNum = $storageManageInfo['in_storage_num'] - $data['allocate_num'];

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $currStorageNum,
                $storageManageInfo['alert_num'],
                $data,
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data['allocate_num'],
            );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                $data,
                $storageInfo['storage_name'],
                $storageInfo['id'],
            );

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('调拨'.var_export($e->getMessage(), true));
        }
    }

    //直接出库
    static public function directOutStorage($data)
    {
        //需出库物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.storage_id',
            'a.materiel_class_id',
            'a.type_id',
            'a.in_storage_num',
            'a.materiel_mean_cost',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.storage_name',
            'd.storage_address',
            'a.alert_num',
            'a.virtual_storage_num',
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where([
                'a.id' => $data['id'],
                'a.delete_flag' => 0
            ])->first()->toArray();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
        }

        if($storageManageInfo['in_storage_num'] < $data['num']) {
            return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        DB::beginTransaction();

        try {
            //出库操作记录日志
            $id=LogOutstorageModel::insert([
                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => 0,
                'next_storage_name' => '',
                'next_storage_address' => '',
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['num'],
                'sell_price' => $storageManageInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time(),
            ]);

            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$data['num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                    ]);
            }

            /* $info = LogOutstorageModel::where('id',$id)->first()->toArray();
            MessageService::sendWxInOrOuStore($storageManageInfo, $i = 1, $data); */

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $storageManageInfo['alert_num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data['num']
                );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $data,
                $storageManageInfo['storage_name'],
                $storageManageInfo['storage_id']
                );

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'],
                $storageManageInfo['storage_name'],
                $data['num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['alert_num'],
                );

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('出库1'.var_export($e->getMessage(), true));
        }
    }

    static public function batchMaterielInfo($id)
    {
        return StorageBatchModel::select(
            'a.batch_no',
            'a.batch_num',
            'a.batch_left_num',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.final_money',
            'd.supplier_name',
            'e.storage_name'
        )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
            ->leftJoin('materiel as d', 'd.id', 'a.materiel_id')
            ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
            ->where('a.id', $id)
            ->first();
    }

    //识别条码
    static public function readBatchNo($data)
    {
        $subBatchInfo = substr($data['batch_no'], -1, 1);
        $condition=[];
        $sInfo=[];
        if($data['code_type']==0){
            $condition['id'] = substr($data['batch_no'],5,strlen($data['batch_no'])-1);
        }elseif($data['code_type']==1){
            $condition['id'] = $data['goods_id'];
            $sInfo = SerialNumberModel::where([
                'serial_no'=>$data['batch_no'],
                'goods_id'=>$data['goods_id']
            ])->first();
        }elseif($data['code_type'] == 3){
            if(strpos($data['batch_no'],'SMYCYJ') !== false){//库存码
                $code = explode('SMYCYJ',$data['batch_no'])[0];
                $mInfo = MaterielTypeModel::where([
                    'delete_flag' => 0,
                    'inventory_code' => $code,
                    'main_id' => $data['main_id']
                ])->first();
                if(empty($mInfo))
                    return ['code' => 1, 'msg' => '暂无库存码信息', 'data' => ''];
            }else {
                $mInfo = MaterielTypeModel::where([
                    'delete_flag' => 0,
                    'bar_code' => $data['batch_no']
                ])->first();

                if (empty($mInfo)) {
                    $mList = MaterielTypeModel::where([
                        'delete_flag' => 0
                    ])->where('number_prefix', '!=', '')->get()->toArray();

                    if (!empty($mList)) {
                        foreach ($mList as $val) {
                            if (strpos($data['batch_no'], $val['number_prefix']) !== false) {
                                $condition['id'] = $val['id'];
                            }
                        }
                    }
                }
                if (empty($condition['id'])) {
                    $condition['bar_code'] = $data['batch_no'];
                }
            }
        }elseif($data['code_type'] == 4){
            $info = StorageManageModel::query()
                ->where([
                'delete_flag' =>0,
                'id'=>$data['batch_no']
            ])->first();
            if(empty($info))
                return ['code' => 1, 'msg' => '暂无库存信息', 'data' => ''];
        }
//        if(!empty($condition)){
//            $info = \App\V3\V3_2\Models\MaterielTypeModel::where($condition)
//                ->where(['delete_flag' => 0])->first();
//            if (!empty($info)) {
//                if ($info['is_product_materiel'] == 1) {//是套餐
//                    $data['goods_id'] = $info['id'];
//                    $data['is_product'] = 1;
//                } elseif($data['code_type'] != 3) {//套餐里的商品
//                    if(!empty($sInfo['parent_id'])||($data['code_type'] != 1)){
//                        $pInfo = \App\V3\V3_2\Models\MaterielProductContentModel::where([
//                            'type_id' => $info['id'],
//                            'delete_flag' => 0
//                        ])->first();
//                       if (!empty($pInfo['product_id'])) {
//                            $data['goods_id'] = $pInfo['product_id'];
//                            $data['is_product']=1;
//                        }
//                    }
//                }
//            } else {
//                $result = ['code' => 1, 'msg' => '商品信息，不存在!', 'data' => ''];
//            }
//            unset($condition);
//        }

        if($data['code_type']==0 && substr($data['batch_no'], 0, 5) == 'smycg') {//商品id
            if(!empty($data['is_product'])){
                $id=$data['goods_id'];
            }else{
                $id=substr($data['batch_no'],5,strlen($data['batch_no'])-1);
            }
            $result = SELF::readGoodsId($id);
        }
        else {
            if($data['code_type']==2) {//批次号
                $result = SELF::getBatchNo($data['batch_no']);

                if(empty($result)) {
                    return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
                }
                $result['type'] = 1;
            }
            else {
                $result = [];
                if($data['code_type']==1 && !empty($data['goods_id']) && !empty($data['batch_no'])){//序列号
                    $result = SELF::readSerialNumber($data);

                    if(empty($result)) {
                        return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
                    }
                    $result['type'] = 0;
                }elseif ($data['code_type']==3 && !empty($data['batch_no'])){//条形码
                    $result = SELF::readBarCode($data);

                    if(empty($result)) {
                        return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
                    }
                    $result['type'] = 0;
                }elseif($data['code_type'] == 4){
                    $result = CheckStorageManageService::readInventoryInfo($data);
                    if(empty($result)) {
                        return ['code' => 1, 'msg' => '该商品，不属于此账号！', 'data' => ''];
                    }
                    $result['type'] = 0;
                }
            }
        }

        return ['code' => 0, 'msg' => 'success', 'data' => $result];
    }

    static public function readGoodsId($batchNo)
    {
        return \App\V3\V3_1\Models\MaterielTypeModel::info($batchNo);
    }

    static public function readBarCode($data){

        $query = \App\V3\V3_2\Models\MaterielTypeModel::select(
            'a.id',
            'a.materiel_name',
            'a.type_name',
            'a.materiel_img',
            'a.materiel_no',
            'a.materiel_class_id',
            'a.remark',
            'a.length',
            'a.width',
            'a.height',
            'a.weight',
            'a.attribute',
            'a.cost',
            'a.selling_price',
            'a.lower_selling_price',
            'a.is_album',
            'a.materiel_unit',
            'a.lower_selling_price',
            'b.class_name as sec_class_name',
            'b.class_no as sec_class_no',
            'c.id as fir_class_id',
            'c.class_name as fir_class_name',
            'a.is_use_serial',
            'a.is_product_materiel',
            'product_use_tag',
            'a.bar_code',
            )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id');
            if(!empty($data['is_product'])){
                $query->where('a.id', $data['goods_id']);
            }else{
                if(strpos($data['batch_no'],'SMYCYJ') !== false){//库存码
                    $code = explode('SMYCYJ',$data['batch_no'])[0];
                    $query -> where('a.inventory_code',$code);
                }else{//条形码
                    $query -> where('a.bar_code',$data['batch_no']);
                }
            }
            return $query->where('a.delete_flag', 0)
            ->with('content', function($query) {
                $query->select(
                    'materiel_product_content.id',
                    'materiel_product_content.type_id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_img',
                    'a.materiel_no',
                    'product_id',
                    'a.selling_price',
                    'materiel_product_content.num',
                    'materiel_product_content.price',
                    'materiel_product_content.total_price',
                    )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_product_content.type_id');
            })
            ->first();

    }
    static private function readSellPackage($batchNo)
    {
        return SellPackageDetailModel::select(
            'a.id',
            'package_no',
            'package_id',
            'package_name',
            'num',
            'price'
        )
            ->from('sell_package_detail as a')
            ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
            ->with('packageContent', function($query) {
                $query->select(
                    'b.in_storage_num',
                    'sell_package_content.materiel_type_id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'c.id as storage_id',
                    'c.storage_name',
                    'sell_package_content.package_detail_id',
                    'sell_package_content.storage_manage_id',
                    'sell_package_content.num',
                    'sell_package_content.total_num'
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'sell_package_content.materiel_type_id')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'sell_package_content.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'sell_package_content.storage_id');
            })
            ->where('package_no', $batchNo)
            ->first();
    }

    //商品批次信息
    static private function readMateriel($batchNo)
    {
        return StorageBatchModel::select(
            'a.id as batch_id',
            'batch_no',
            'batch_num',
            'batch_left_num',
            'b.in_storage_num',
            'b.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_img',
            'c.materiel_no',
            'd.id as storage_id',
            'd.storage_name',
            'a.storage_manage_id',
            'f.price as sell_price'
        )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'b.type_id', '=', 'c.id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('sell_goods_detail_batch as e', 'e.storage_batch_id', '=', 'a.id')
            ->leftJoin('sell_goods_detail as f', 'f.id', '=', 'e.sell_goods_detail_id')
            ->where('batch_no', $batchNo)
            ->first();
    }
    static private function getBatchNo($batchNo){
        $info = StorageBatchModel::select(
            'b.id',
            'a.id as batch_id',
            'batch_no',
            'batch_num',
            'batch_left_num',
            'b.in_storage_num',
            'b.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_img',
            'c.materiel_no',
            'd.id as storage_id',
            'd.storage_name',
            'a.storage_manage_id',
            'c.selling_price',
            'c.is_use_serial',
            'c.is_product_materiel',
            'c.length',
            'c.width',
            'c.height',
            'c.weight',
            'c.attribute',
            'c.cost',
            'c.last_cost',
            'c.lower_selling_price',
            'c.remark',
            'c.bar_code',
            'e.shelf_name',
            'f.location_name',
            'c.attribute',
            DB::raw('SUM(in_storage_num) as total_amount')
            )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'b.type_id', '=', 'c.id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('storage_shelf as e', 'e.id', '=', 'b.shelf_id')
            ->leftJoin('storage_shelf_location as f', 'f.id', '=', 'b.location_id')
            ->where([
                'batch_no'=> $batchNo,
                'a.delete_flag'=>0,
                'b.delete_flag'=>0,
                'c.delete_flag'=>0,
                'd.delete_flag'=>0,
            ])->first()->toArray();
            if(empty($info['batch_id']) || empty($info['type_id'])){
                return [];
            }
            $info['product_content'] =[];
            if($info['is_product_materiel'] == 1){
                $info['product_content'] = MaterielProductContentModel::select(
                    'a.id',
                    'b.materiel_name',
                    'b.type_name',
                    'b.materiel_img',
                    'b.materiel_no',
                    'a.product_id',
                    'a.num',
                    'a.price',
                    'a.type_id',
                    'a.total_price',
                    'b.is_use_serial'
                    )
                    ->from('materiel_product_content as a')
                    ->leftJoin('materiel_type as b','b.id','=','a.type_id')
                    ->where('a.product_id',$info['type_id'])->get()->toArray();
            }
            return $info;
    }
    /**
     * 序列号查询（打码）
     * @param unknown $serialNubmer
     */
    static private function readSerialNumber($data){
        $serialInfo = \App\V3\V3_2_7\Models\SerialNumberModel::where([
            'serial_no'=>$data['batch_no'],
            'goods_id'=>$data['goods_id'],
            'delete_flag' => 0
        ])->first();
        if(empty($serialInfo)) return "";
        //查询是否是组件序列号，如果是返回组件套餐id
        $query = SerialNumberModel::select(
            'b.id',
            'b.type_id',
            'c.materiel_name',
            'c.materiel_img',
            'd.shelf_name',
            'e.location_name',
            'c.type_name',
            'c.materiel_no',
            'b.storage_name',
            'b.storage_id',
            'b.shelf_id',
            'b.location_id',
            'c.selling_price',
            'c.is_use_serial',
            'c.is_product_materiel',
            'c.length',
            'c.width',
            'c.height',
            'c.weight',
            'c.attribute',
            'c.cost',
            'c.last_cost',
            'c.lower_selling_price',
            'c.remark',
            'c.bar_code',
            DB::raw('SUM(in_storage_num) as total_amount')
            )->from('serial_number as a');
        if(!empty($serialInfo['parent_id'])){
            $serialInfo = SerialNumberModel::where(['id'=>$serialInfo['parent_id']])->first();
        }
        $query ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'b.type_id', '=', 'c.id')
            ->leftJoin('storage_shelf as d', 'd.id', '=', 'b.shelf_id')
            ->leftJoin('storage_shelf_location as e', 'e.id', '=', 'b.location_id')
            -> where('serial_no', $serialInfo['serial_no'])
            -> where('a.goods_id', $serialInfo['goods_id']);
            $info = $query->where('b.delete_flag',0)
            ->where('c.delete_flag',0)
            ->first();

            if(empty($info['id']) || empty($info['type_id'])){
                return [];
            }
            $info['product_content'] =[];
            $info['parent_serial_info'] =[];

            if(!empty($info) && $info['is_product_materiel'] == 1){
                $productList = MaterielProductContentModel::select(
                    'a.id',
                    'b.materiel_name',
                    'b.type_name',
                    'b.materiel_img',
                    'b.materiel_no',
                    'a.product_id',
                    'a.num',
                    'a.price',
                    'a.type_id',
                    'a.total_price',
                    'b.is_use_serial'
                    )
                    ->from('materiel_product_content as a')
                    ->leftJoin('materiel_type as b','b.id','=','a.type_id')
                    ->where('a.product_id',$info['type_id'])->get()->toArray();
                    if(!empty($productList)){

                        $pSreialNumberInfo=SerialNumberModel::where([
                            'goods_id'=>$info['type_id'],
                            'status'=>1
                        ])->first();

                        if(!empty($pSreialNumberInfo)){
                            foreach ($productList as &$pVal){
                                $pVal['children_serial_info']=[];
                                $cSreialnumberList=SerialNumberModel::where([
                                    'goods_id'=>$pVal['type_id'],
                                    'status'=>1,
                                    'parent_id'=>$pSreialNumberInfo['id']
                                ])->get();
                                if(!empty($cSreialnumberList)){

                                    $pVal['children_serial_info']=$cSreialnumberList;
                                }


                            }
                            $info['parent_serial_info']=$pSreialNumberInfo;
                        }
                        $info['product_content'] = $productList;
                    }
            }

            return $info;
    }

    //商品库存批次列表
    static public function materielBatchList($typeId, $sellId, $type, $data)
    {
        $result = StorageManageModel::materielBatchList($typeId, $data);
//        if($type == 0) {
//            $sellGoodsBatchInfo = SellGoodsDetailModel::getBatchInfo($sellId);
//
//            if(empty($sellGoodsBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellGoodsBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }
//        else {
//            $sellPackageBatchInfo = SellPackageContentModel::getBatchInfo($sellId, $data);
//
//            if(empty($sellPackageBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellPackageBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }

        return $result;
    }

    static public function fastOutStorage($data)
    {
        if(isset($data['sell_id'])) {
            $sellInfo = SellModel::where('id', $data['sell_id'])->first();
            if($sellInfo['repeal_status']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已撤销',
                    'data' => ''
                ];
            }

            if($sellInfo['delete_flag']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已删除',
                    'data' => ''
                ];
            }

            if($sellInfo['out_status'] == 2) {
                return [
                    'code' => 1,
                    'msg' => 'success',
                    'data' => [
                        'is_finished' => 1
                    ]
                ];
            }
        }

        $batchNoTag = substr($data['batch_no'], -1, 1);

        if($batchNoTag == 'a') {//套餐编码
            $result = SELF::packageFastOut($data);
        }
        else {//商品编码
            $result = SELF::materielFastOut($data);
        }

        DB::beginTransaction();

        try {
            if(isset($data['sell_id'])) {
                //更新销售入库状态
                SellModel::where('id',$data['sell_id'])->update(['out_status'=>1, 'prepare_out_status' => 0]);

                $sellGoodsInfo = SellGoodsDetailModel::where('sell_id', $data['sell_id'])
                    ->whereRaw('num > out_num')
                    ->first();

                $sellPackageInfo = SellPackageDetailModel::where('sell_id', $data['sell_id'])
                    ->whereRaw('num > out_num')
                    ->first();

                if(empty($sellGoodsInfo) && empty($sellPackageInfo)) {
                    SellModel::where('id',$data['sell_id'])->update(['out_status'=>2,'prepare_out_status' => 0]);//全部完成更新状态
                    CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$data['sell_id']])
                        ->update(['status'=>1,'out_in_status'=>0]);
                }
                else {
                    CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$data['sell_id']])
                        ->update(['out_in_status'=>1]);
                }
            }

            DB::commit();
            return $result;
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('快速出库，出库状态异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    static private function packageFastOut($data)
    {
        DB::beginTransaction();
        try {
            $sellPackageBatchInfo = SellPackageDetailModel::select(
                'a.id',
                'a.package_id',
                'c.package_name',
                'out_num',
                'a.num'
            )
                ->from('sell_package_detail as a')
                ->leftJoin('package as c', 'c.id', '=', 'a.package_id')
                ->where('a.sell_id', $data['sell_id'])
                ->where('package_no', $data['batch_no'])
                ->first();

            if(empty($sellPackageBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '套餐批次不存在，请重试',
                    'data' => ''
                ];
            }

            if($sellPackageBatchInfo['num'] == $sellPackageBatchInfo['out_num']) {
                return ['code' => 1, 'msg' => '该套餐已全部出库', 'data' => ''];
            }

            $logPackageBasicInfo = [
                'package_id' => $sellPackageBatchInfo['package_id'],
                'package_name' => $sellPackageBatchInfo['package_name'],
                'num' => 1,
                'all_id_type' => 2,
                'all_id' => $data['sell_id'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'created_at' => time()
            ];

            $logId = LogPackageModel::insertGetId($logPackageBasicInfo);

            if(($sellPackageBatchInfo['num'] - $sellPackageBatchInfo['out_num']) < 1) {
                return [
                    'code' => 1,
                    'msg' => '可出库套餐数不足',
                    'data' => ''
                ];
            }

            if($data['out_way']) {

                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'num'
                )
                    ->from('sell_package_content as a')
                    ->with('packageBatchInfo', function($query) {
                        $query->select(
                            'a.id',
                            'sell_package_batch.storage_manage_id',
                            'sell_package_content_id',
                            'num',
                            'b.storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'b.type_id',
                            'd.materiel_name',
                            'd.type_name',
                            'd.materiel_no',
                            'in_storage_num',
                            'materiel_mean_cost',
                            'e.id as materiel_class_id',
                            'e.class_name',
                            'e.class_no',
                            'alert_num',
                            'in_storage_num',
                            'batch_left_num'
                        )
                            ->leftJoin('storage_batch as a', 'sell_package_batch.storage_batch_id', '=', 'a.id')
                            ->leftJoin('storage_manage as b', 'sell_package_batch.storage_manage_id', '=', 'b.id')
                            ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                            ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                            ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id');
                    })
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach($sellPackageContent as $value) {
                    $totalNum = 0;
                    foreach($value['package_batch_info'] as $val) {
                        $totalNum += $val['batch_left_num'];
                        MessageService::sendAlertSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['alert_num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name'],
                            $value['num']
                        );

                        MessageService::sendShortSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name'],
                        );

                        MessageService::sendOutSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['storage_name'],
                            $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['alert_num'],
                        );

                        $logPackageContentData[] = [
                            'log_package_id' => $logId,
                            'package_id' => $sellPackageBatchInfo['package_id'],
                            'storage_id' => $val['storage_id'],
                            'storage_name' => $val['storage_name'],
                            'storage_address' => $val['storage_address'],
                            'materiel_class_id' => $val['materiel_class_id'],
                            'materiel_class_name' => $val['class_name'],
                            'materiel_class_no' => $val['class_name'],
                            'materiel_type_id' => $val['type_id'],
                            'materiel_name' => $val['materiel_name'],
                            'type_name' => $val['type_name'],
                            'materiel_no' => $val['materiel_no'],
                            'operate_num' => $value['num'],
                            'out_storage_manage_id' => $val['storage_manage_id'],
                            'last_storage_num' => $val['in_storage_num'],
                            'next_storage_num' => $val['in_storage_num'] - $value['num'],
                            'all_id_type' => 4,
                            'all_id' => $data['sell_id'],
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'storage_batch_id' => $val['id'],
                            'created_at' => time()
                        ];

                        if($val['in_storage_num'] < $value['num']) {
                            return [
                                'code' => 1,
                                'msg' => '库存不足，无法出库',
                                'data' => ''
                            ];
                        }

                        StorageManageModel::where('id', $val['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num -".$value['num']),
                                'virtual_storage_num' => DB::raw("virtual_storage_num -".$value['num'])
                            ]);

                        StorageBatchModel::where('id', $val['id'])
                            ->decrement('batch_left_num', $value['num']);
                    }

                    if($totalNum < $value['num']) {
                        return [
                            'code' => 1,
                            'msg' => '批次库存数量不足，无法出库',
                            'data' => ''
                        ];
                    }
                }
                LogPackageContentModel::insert($logPackageContentData);
            }
            else {
                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'storage_manage_id',
                    'num',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'b.type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'in_storage_num',
                    'materiel_mean_cost',
                    'e.id as materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'alert_num'
                )
                    ->from('sell_package_content as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach($sellPackageContent as $value) {
                    if($value['num'] > $value['in_storage_num']) {
                        return [
                            'code' => 1,
                            'msg' => '库存数不足，无法完成出库',
                            'data' => ''
                        ];
                    }

                    $arr[] = [
                        'storage_manage_id' => $value['storage_manage_id'],
                        'operate_num' => $value['num'],
                        'in_storage_num' => $value['in_storage_num'],
                        'alert_num' => $value['in_storage_num'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                    ];

                    $logPackageContentData[] = [
                        'log_package_id' => $logId,
                        'package_id' => $sellPackageBatchInfo['package_id'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_class_id' => $value['materiel_class_id'],
                        'materiel_class_name' => $value['class_name'],
                        'materiel_class_no' => $value['class_name'],
                        'materiel_type_id' => $value['type_id'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'materiel_no' => $value['materiel_no'],
                        'operate_num' => $value['num'],
                        'out_storage_manage_id' => $value['storage_manage_id'],
                        'last_storage_num' => $value['in_storage_num'],
                        'next_storage_num' => $value['in_storage_num'] - $value['num'],
                        'all_id_type' => 4,
                        'all_id' => $data['sell_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time()
                    ];
                }

                LogPackageContentModel::insert($logPackageContentData);

                foreach($arr as $v) {
                    MessageService::sendAlertSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['alert_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name'],
                        $v['operate_num']
                    );

                    MessageService::sendShortSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name'],
                    );

                    MessageService::sendOutSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['storage_name'],
                        $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['alert_num'],
                    );

                    StorageManageModel::where('id', $v['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num -".$v['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num -".$v['operate_num'])
                        ]);
                }
            }

            SellPackageDetailModel::where('id', $sellPackageBatchInfo['id'])
                ->increment('out_num', 1);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('销售单套餐快速出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '销售单套餐快速出库异常', 'data' => ''];
        }
    }

    static private function materielFastOut($data)
    {
        if(isset($data['sell_id'])) {
            return SELF::materielSellFastOut($data);
        }
        else {
            return SELF::materielDirectlyFastOut($data);
        }
    }

    static private function materielDirectlyFastOut($data)
    {
        DB::beginTransaction();

        try {
            $storageBatchInfo = StorageBatchModel::select(
                'a.id as batch_id',
                'batch_left_num',
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'c.materiel_name',
                'c.type_name',
                'c.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
            )
                ->from('storage_batch as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('batch_no', $data['batch_no'])->first();

            if(empty($storageBatchInfo)) {
                return ['code' => 1, 'msg' => '批次不存在，无法出库', 'data' => ''];
            }

            if($storageBatchInfo['batch_left_num'] < 1) {
                return ['code' => 1, 'msg' => '库存批次数量不足,无法出库', 'data' => ''];
            }

            if($storageBatchInfo['in_storage_num'] < 1) {
                return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
            }

            $logOutInfo = [
                'type' => 0,
                'storage_batch_id' => $storageBatchInfo['batch_id'],
                'storage_id' => $storageBatchInfo['storage_id'],
                'storage_name' => $storageBatchInfo['storage_name'],
                'storage_address' => $storageBatchInfo['storage_address'],
                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                'materiel_class_name' => $storageBatchInfo['class_name'],
                'materiel_class_no' => $storageBatchInfo['class_no'],
                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                'materiel_name' => $storageBatchInfo['materiel_name'],
                'type_name' => $storageBatchInfo['type_name'],
                'materiel_no' => $storageBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'out_storage_time' => time(),
                'created_at' => time()
            ];

            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num'],
            );

            LogOutStorageModel::insert($logOutInfo);

            StorageBatchModel::where('id', $storageBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            SellGoodsDetailModel::where('id',$storageBatchInfo['sell_goods_detail_id'])
                ->increment('out_num', 1);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('商品直接出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品直接出库异常，请重试', 'data' => ''];
        }
    }

    //销售单快速出库
    static private function materielSellFastOut($data)
    {
        if($data['out_way']) {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'b.id as sell_goods_batch_id',
                'a.materiel_type_id',
                'f.materiel_name',
                'f.type_name',
                'f.materiel_no',
                'a.num',
                'a.out_num',
                'b.num as batch_num',
                'b.rest_num',
                'storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'e.storage_name',
                'e.storage_address',
                'd.id as storage_manage_id',
                'f.materiel_class_id',
                'g.class_name',
                'g.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.price'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('sell_goods_detail_batch as b', 'b.sell_goods_detail_id', '=', 'a.id')
                ->leftJoin('storage_batch as c', 'c.id', '=', 'b.storage_batch_id')
                ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
                ->leftJoin('storage as e', 'e.id', '=', 'd.storage_id')
                ->leftJoin('materiel_type as f', 'f.id', '=', 'd.type_id')
                ->leftJoin('materiel_class as g', 'g.id', '=', 'f.materiel_class_id')
                ->where('c.batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('b.rest_num', 'desc')
                ->first();

            //商品已设置批次号
            if(!empty($sellGoodsBatchInfo)) {
                if($sellGoodsBatchInfo['num'] == $sellGoodsBatchInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['rest_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '商品所设置的可出库批次数量不足',
                        'data' => ''
                    ];
                }
            }
            else {
                //商品批次号信息
                $sellGoodsBatchInfo = StorageBatchModel::select(
                    'a.*',
                    'type_id',
                    'in_storage_num',
                    'b.type_id as materiel_type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'd.materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'materiel_mean_cost',
                    'alert_num',
                )
                    ->from('storage_batch as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('batch_no', $data['batch_no'])
                    ->first();

                $sellGoodsBatchInfo['price'] = $sellGoodsBatchInfo['materiel_mean_cost'];

                if(empty($sellGoodsBatchInfo)) {
                    return ['code' => 1, 'msg' => '无此批次信息', 'data' => ''];
                }

                //销售单内商品信息
                $sellGoodsInfo = SellGoodsDetail::where([
                    'sell_id' => $data['sell_id'],
                    'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id']
                ])->first();

                if(empty($sellGoodsInfo)) {
                    return ['code' => 1, 'msg' => '当前批次号不属于该商品', 'data' => ''];
                }
//
                if($sellGoodsInfo['num'] == $sellGoodsInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                $sellGoodsBatchInfo['storage_batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['id'] = $sellGoodsInfo['id'];
                $sellGoodsBatchInfo['sell_goods_id'] = 0;
            }
        }
        else {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'a.materiel_type_id',
                'e.materiel_name',
                'e.type_name',
                'e.materiel_no',
                'c.id as storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.id as storage_manage_id',
                'e.materiel_class_id',
                'f.class_name',
                'f.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.num',
                'a.out_num',
                'a.price'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
                ->leftJoin('storage_batch as c', 'c.storage_manage_id', '=', 'b.id')
                ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
                ->where('batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('batch_left_num', 'desc')
                ->first();

            if(empty($sellGoodsBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '销售单内无此批次信息',
                    'data' => ''
                ];
            }
        }

        if($sellGoodsBatchInfo['in_storage_num'] < 1) {
            return [
                'code' => 1,
                'msg' => '商品库存数量不足',
                'data' => ''
            ];
        }

        $logOutInfo = [
            'type' => 0,
            'storage_batch_id' => $sellGoodsBatchInfo['storage_batch_id'],
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'out_storage_time' => time(),
            'fact_out_time' => time(),
            'created_at' => time()
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
        );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
           $sellGoodsBatchInfo['storage_name'],
            1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num'],
        );

        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);

            SellGoodsDetailBatchModel::where('id', $sellGoodsBatchInfo['sell_goods_id'])
                ->decrement('rest_num', 1);

            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            StorageBatchModel::where('id', $sellGoodsBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            LogOutStorageModel::insert($logOutInfo);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('快速出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    /**
     * 清除库存信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/13 16:50
     * @return array
     */
    static public function clear($data)
    {
        DB::beginTransaction();

        $storageManageInfo = StorageManageModel::where([
            'storage_id' => $data['id'],
            'delete_flag' => 0
        ])->get()->toArray();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '要清除的目标库存信息不存在，无法操作，请重试', 'data' => ''];
        }

        try {
            //获取库存id
            $storageManageId = [];
            foreach($storageManageInfo as $value) {
                $storageManageId[] = $value['id'];
            }

            //清除库存信息
            StorageManageModel::whereIn('id', $storageManageId)
                ->update([
                    'in_storage_num' => 0,
                    'virtual_storage_num' => 0
                ]);

            //清除库存批次信息
            StorageBatchModel::whereIn('storage_manage_id', $storageManageId)
                ->update([
                    'batch_left_num' => 0
                ]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('清除批次信息'.var_export($e->getMessage()));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

}
